#include "Minimization.h" #include #include #include #include #include /* Nasty global variables to store pointers to Java environment and methods so that we can use them in different parts of this C code. */ JNIEnv *globalJavaEnv; jobject globaljavaobject; jmethodID globalConfunID; jmethodID globalObjfunID; /* This routine has the interface required by NAG routine e04ucf for argument confun. It makes calls back to the Java version of confun */ void confunFun(int *mode, int *ncnln, int *n, int *ldcj, int needc[], double x[], double c[], double cjac[], int *nstate, int iuser[], double user[]) { int i; int *jneedcpt; double *jxpt, *jcpt, *jcjacpt; /* First create some Java arrays to pass to confun */ jintArray jneedc = (*globalJavaEnv)->NewIntArray(globalJavaEnv, *ncnln); jdoubleArray jx = (*globalJavaEnv)->NewDoubleArray(globalJavaEnv, *n); jdoubleArray jc = (*globalJavaEnv)->NewDoubleArray(globalJavaEnv, *ncnln); jdoubleArray jcjac = (*globalJavaEnv)->NewDoubleArray(globalJavaEnv, ((*ldcj)*(*n))); /* Copy input arguments to Java arrays needc and x */ jneedcpt = (*globalJavaEnv)->GetIntArrayElements(globalJavaEnv, jneedc, 0); jxpt = (*globalJavaEnv)->GetDoubleArrayElements(globalJavaEnv, jx, 0); for (i = 0; i < *ncnln; i++) jneedcpt[i] = needc[i]; for (i = 0; i < *n; i++) jxpt[i] = x[i]; /* Release array elements back to Java (this puts the values back into Java arrays jneedc and jx) */ (*globalJavaEnv)->ReleaseIntArrayElements(globalJavaEnv, jneedc, jneedcpt, 0); (*globalJavaEnv)->ReleaseDoubleArrayElements(globalJavaEnv, jx, jxpt, 0); /* Call the Java method via its method ID */ (*globalJavaEnv)->CallVoidMethod(globalJavaEnv, globaljavaobject, globalConfunID, (jint)(*mode), (jint) (*ncnln), (jint)(*n), (jint)(*ldcj), jneedc, jx, jc, jcjac, (jint)(*nstate)); /* Copy results from Java arrays back to C arrays */ jcpt = (*globalJavaEnv)->GetDoubleArrayElements(globalJavaEnv, jc, 0); jcjacpt = (*globalJavaEnv)->GetDoubleArrayElements(globalJavaEnv, jcjac, 0); for (i = 0; i < *ncnln; i++) c[i] = jcpt[i]; for (i = 0; i < (*ldcj)*(*n); i++) cjac[i] = jcjacpt[i]; /* Release array elements back to Java to free memory */ (*globalJavaEnv)->ReleaseDoubleArrayElements(globalJavaEnv, jc, jcpt, 0); (*globalJavaEnv)->ReleaseDoubleArrayElements(globalJavaEnv, jcjac, jcjacpt, 0); } /* This routine has the interface required by NAG routine e04ucf for argument objfun. It makes calls back to the Java version of objfun */ void objfunFun(int *mode, int *n, double x[], double *objf, double objgrd[], int *nstate, int iuser[], double user[]) { int i; double *jobjgrdpt; /* First create some Java arrays to pass to objfun */ jdoubleArray jx = (*globalJavaEnv)->NewDoubleArray(globalJavaEnv, *n); jdoubleArray jobjgrd = (*globalJavaEnv)->NewDoubleArray(globalJavaEnv, *n); /* Copy input array x to Java array jx */ double *jxpt = (*globalJavaEnv)->GetDoubleArrayElements(globalJavaEnv, jx, 0); for (i = 0; i < *n; i++) jxpt[i] = x[i]; /* Release array elements back to Java (this puts the values into jx) */ (*globalJavaEnv)->ReleaseDoubleArrayElements(globalJavaEnv, jx, jxpt, 0); /* Call Java objfun which fills in array objgrd and returns objf */ *objf = (*globalJavaEnv)->CallDoubleMethod(globalJavaEnv, globaljavaobject, globalObjfunID, (jint) (*mode), (jint) (*n), jx, jobjgrd, (jint) (*nstate)); /* Get results back from Java to C array objgrd */ jobjgrdpt = (*globalJavaEnv)->GetDoubleArrayElements(globalJavaEnv, jobjgrd, 0); for (i = 0; i < *n; i++) objgrd[i] = jobjgrdpt[i]; /* Release array elements back to Java to free memory */ (*globalJavaEnv)->ReleaseDoubleArrayElements(globalJavaEnv, jobjgrd, jobjgrdpt, 0); } JNIEXPORT jint JNICALL Java_Minimization_e04ucf ( JNIEnv *env, jobject object, jint n, jint nclin, jint ncnln, jdoubleArray a, jint lda, jdoubleArray bl, jdoubleArray bu, jstring confun, jstring objfun, jdoubleArray objf, jdoubleArray objgrd, jdoubleArray x ) { /* Local variables and arrays */ int ldcj; int ldr; int iter; int *istate; double *c; double *cjac; double *clamda; double *r; int liwork; int *iwork; int lwork; double *work; int ifail; /* N.B. we choose not to use iuser and user arrays in our evaluation functions, so these are empty arrays. */ int iuser[1]; double user[1]; jclass cls; const char *confunction; const char *objfunction; jdouble *a_pt, *bl_pt, *bu_pt, *x_pt, *objf_pt, *objgrd_pt; /* Array leading dimension information required by the Fortran routine */ if (ncnln > 0) ldcj = ncnln; else ldcj = 1; ldr = n; /* Compute the amount of workspace we need to supply to e04ucf */ liwork = 3 * n + nclin + 2 * ncnln; if (ncnln == 0 && nclin == 0) lwork = 20 * n; else if (ncnln == 0 && nclin > 0) lwork = 2 * n*n + 20 * n + 11 * nclin; else lwork = 2 * n*n + n*nclin + 2*n*ncnln + 20*n + 11*nclin + 21*ncnln; /* Allocate arrays of appropriate size. */ /* Note that we store cjac as a one dimensional array rather than a 2D array as in Fortran, for convenience in communication with Java. */ istate = (int *)malloc((n+nclin+ncnln)*sizeof(int)); c = (double *)malloc((ncnln)*sizeof(double)); cjac = (double *)malloc((ldcj*n)*sizeof(double)); clamda = (double *)malloc((n+nclin+ncnln)*sizeof(double)); r = (double *)malloc((ldr*n)*sizeof(double)); iwork = (int *)malloc((liwork)*sizeof(int)); work = (double *)malloc((lwork)*sizeof(double)); /* Copy the Java env pointers to global space so that confunFun and objfunFun can access them. */ globalJavaEnv = env; globaljavaobject = object; /* Get hold of the name of the user's Java evaluation functions. */ confunction = (*env)->GetStringUTFChars(env, confun, 0); objfunction = (*env)->GetStringUTFChars(env, objfun, 0); /* Now we have the Java evaluation function names we can use them to get hold of handles (method IDs) to the functions. Once more, the method IDs are stored globally so that confunFun and objfunFun can use them. Note that the Java function signatures must be correct. You can find out the signatures after compiling the Java program Minimization.java by using the command % javap -private -s Minimization */ cls = (*env)->GetObjectClass(env, object); globalConfunID = (*env)->GetMethodID(env, cls, confunction, "(IIII[I[D[D[DI)V"); globalObjfunID = (*env)->GetMethodID(env, cls, objfunction, "(II[D[DI)D"); /* Free up the Java string argument so we don't leak memory. */ (*env)->ReleaseStringUTFChars(env, confun, confunction); (*env)->ReleaseStringUTFChars(env, objfun, objfunction); if (globalConfunID == 0) { printf("Cannot find confun method \"%s\" with signature \"(IIII[I[D[D[DI)V\"\n", confunction); return -1; } if (globalObjfunID == 0) { printf("Cannot find objfun method \"%s\" with signature \"(II[D[DI)D\"\n", objfunction); return -1; } /* Extract the arrays from Java */ a_pt = (*env)->GetDoubleArrayElements(env, a, 0); bl_pt = (*env)->GetDoubleArrayElements(env, bl, 0); bu_pt = (*env)->GetDoubleArrayElements(env, bu, 0); objf_pt = (*env)->GetDoubleArrayElements(env, objf, 0); objgrd_pt = (*env)->GetDoubleArrayElements(env, objgrd, 0); x_pt = (*env)->GetDoubleArrayElements(env, x, 0); /* Call to main NAG Library routine e04ucf */ ifail = -1; #ifdef WINDOWS E04UCF #else e04ucf_ #endif (&n, &nclin, &ncnln, &lda, &ldcj, &ldr, a_pt, bl_pt, bu_pt, confunFun, objfunFun, &iter, istate, c, cjac, clamda, objf_pt, objgrd_pt, r, x_pt, iwork, &liwork, work, &lwork, iuser, user, &ifail); /* Release the array elements back to Java and free memory. */ (*env)->ReleaseDoubleArrayElements(env, a, a_pt, 0); (*env)->ReleaseDoubleArrayElements(env, bl, bl_pt, 0); (*env)->ReleaseDoubleArrayElements(env, bu, bu_pt, 0); (*env)->ReleaseDoubleArrayElements(env, objf, objf_pt, 0); (*env)->ReleaseDoubleArrayElements(env, objgrd, objgrd_pt, 0); (*env)->ReleaseDoubleArrayElements(env, x, x_pt, 0); return ifail; } // Interface to option setting routine e04uef JNIEXPORT void JNICALL Java_Minimization_e04uef (JNIEnv *env, jobject object, jstring option) { const char *coption; /* Get hold of the Java option string. */ coption = (*env)->GetStringUTFChars(env, option, 0); /* Call the option setting routine */ #ifdef WINDOWS E04UEF(coption, strlen(coption)); #else e04uef_(coption, strlen(coption)); #endif /* Free up the Java string argument so we don't leak memory. */ (*env)->ReleaseStringUTFChars(env, option, coption); }